package com.example.qt.ptplatform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.qt.ptplatform.dto.LeaderboardDto;
import com.example.qt.ptplatform.entity.*;
import com.example.qt.ptplatform.mapper.*;
import com.example.qt.ptplatform.service.PineconeService;
import com.example.qt.ptplatform.service.TorrentReportService;
import com.example.qt.ptplatform.service.UserService;
import com.example.qt.ptplatform.service.TorrentService;
import com.example.qt.ptplatform.utils.JsonResult;
import com.turn.ttorrent.common.Optional;
import io.pinecone.clients.Index;
import io.pinecone.clients.Pinecone;
import org.openapitools.db_data.client.ApiException;
import org.openapitools.db_data.client.model.SearchRecordsResponse;
import org.openapitools.db_data.client.model.SearchRecordsVector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import io.pinecone.clients.Pinecone;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TorrentMapper torrentMapper;  // 注入 TorrentMapper 用于查询 torrent 数据
    @Autowired
    private DownloadMapper downloadMapper;
    @Autowired
    private PointRecordMapper pointRecordMapper;
    @Autowired
    private LoginLogMapper loginLogMapper;

    @Autowired
    private TorrentService torrentService;

    @Autowired
    private TorrentReportService torrentReportService;

    private final Pinecone pinecone;

    private final PineconeService pineconeService;

    @Autowired
    public UserServiceImpl(Pinecone pinecone,PineconeService pineconeService) {
        this.pinecone = pinecone;
        this.pineconeService = pineconeService;
    }

    @Override
    public boolean isUsernameExist(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username)) != null;
    }

    @Override
    public User findByUsername(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
    }

    @Override
    public User getById(Integer id) {
        // 可以直接调用父类的方法
        return super.getById(id);
    }

    @Override
    public Optional<User> findByPeerID(String peerID) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(User::getPeerId, peerID);
        User user = userMapper.selectOne(wrapper);
        return Optional.of(user);
    }

    @Override
    public Integer getUserPoints(Integer userId) {
        return userMapper.getUserPointsById(userId);
    }

    public void updateLikedTorrentsAndTags(Integer userId, Integer torrentId, String type) {
        // 获取当前用户信息
        User user = this.getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 获取种子信息
        Torrent torrent = torrentMapper.selectById(torrentId);
        if (torrent == null) {
            throw new RuntimeException("种子不存在");
        }

        // 更新用户的liked_torrents字段
        String likedTorrents = user.getLikedTorrents();
        if (likedTorrents == null) {
            likedTorrents = "";
        }
        likedTorrents += torrentId + ",";  // 这里假设用逗号分隔
        user.setLikedTorrents(likedTorrents);

        // 更新用户的liked_tags字段
        String likedTags = user.getLikedTags();
        if (likedTags == null) {
            likedTags = "";
        }

        // 获取种子的标签
        String[] tags = torrent.getTags().replace("[", "").replace("]", "").split(",");
        for (String tag : tags) {
            tag = tag.trim();  // 去除空格
            // 查找该标签是否已经存在
            String tagScore = getTagScore(likedTags, tag);
            if (tagScore == null) {
                if(type=="watch")
                    likedTags += tag + ":1.5,";  // 观看行为，增加1.5分
                if(type=="download")
                    likedTags += tag + ":3,";
            } else {
                // 如果已经存在该标签，则更新分数
                if(type=="watch")
                    likedTags = likedTags.replace(tag + ":" + tagScore, tag + ":" + (Double.parseDouble(tagScore) + 1.5));
                if(type=="download")
                    likedTags = likedTags.replace(tag + ":" + tagScore, tag + ":" + (Double.parseDouble(tagScore) + 3));
            }
        }
        user.setLikedTags(likedTags);

        // 保存更新后的用户信息
        this.updateById(user);
    }

    // 辅助方法：获取标签的分数
    private String getTagScore(String likedTags, String tag) {
        String[] tagList = likedTags.split(",");
        for (String entry : tagList) {
            if (entry.contains(tag)) {
                return entry.split(":")[1];
            }
        }
        return null;
    }

    public JsonResult recommendSimilarUsers(Integer userId) {
        // 日志实例
        Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

        User currentUser = this.getById(userId);
        if (currentUser == null) {
            return JsonResult.error("用户不存在");
        }

        // 获取当前用户的 liked_tags
        String currentUserLikedTags = currentUser.getLikedTags();
        if (currentUserLikedTags == null || currentUserLikedTags.isEmpty()) {
            return JsonResult.error("当前用户没有标签数据");
        }

        // 获取所有用户的 liked_tags
        List<User> allUsers = this.list();
        List<UserSimilarity> similarities = new ArrayList<>();

        // 计算与其他用户的相似度
        for (User user : allUsers) {
            if (user.getUserId().equals(userId)) continue;  // 跳过当前用户

            String otherUserLikedTags = user.getLikedTags();
            if (otherUserLikedTags != null && !otherUserLikedTags.isEmpty()) {
                double similarity = calculateCosineSimilarity(currentUserLikedTags, otherUserLikedTags);
                similarities.add(new UserSimilarity(user.getUserId(), similarity));

                // 输出每个用户与 user_id=3 的相似度
                logger.info("用户 {} 与 用户 {} 的相似度评分: {}", user.getUserId(), userId, similarity);
            }
        }

        // 按相似度降序排序
        similarities.sort((s1, s2) -> Double.compare(s2.getSimilarity(), s1.getSimilarity()));

        if (similarities.size() < 2) {
            return JsonResult.error("没有足够的用户进行推荐");
        }

        // 获取最相似的两个用户
        Integer user1Id = similarities.get(0).getUserId();
        Integer user2Id = similarities.get(1).getUserId();

        User user1 = this.getById(user1Id);
        User user2 = this.getById(user2Id);

        String likedTorrentsUser1 = user1.getLikedTorrents();
        String likedTorrentsUser2 = user2.getLikedTorrents();

        String likedTorrentsFromPinecone = torrentFormPinecone(currentUser.getLikedTags());

        // 输出用户1和用户2的喜欢的种子列表
        logger.info("用户 ({}) 喜欢的种子: {}", user1Id, likedTorrentsUser1);
        logger.info("用户 ({}) 喜欢的种子: {}", user2Id, likedTorrentsUser2);
        logger.info("松果推荐的种子: {}", likedTorrentsFromPinecone);

        Set<String> recommendedTorrents = new HashSet<>();

        // 获取当前用户喜欢的种子
        Set<String> currentUserLikedSet = new HashSet<>(Arrays.asList(currentUser.getLikedTorrents().split(",")));

        Set<String> likedTorrentsUser1Set = new HashSet<>(Arrays.asList(likedTorrentsUser1.split(",")));
        Set<String> likedTorrentsUser2Set = new HashSet<>(Arrays.asList(likedTorrentsUser2.split(",")));
        Set<String> likedTorrentsPineconeSet = new HashSet<>(Arrays.asList(likedTorrentsFromPinecone.split(",")));

        // 排除当前用户已经喜欢的种子
        likedTorrentsUser1Set.removeAll(currentUserLikedSet);
        likedTorrentsUser2Set.removeAll(currentUserLikedSet);
        likedTorrentsPineconeSet.removeAll(currentUserLikedSet);

        logger.info("用户 ({}) 喜欢的种子: {}", currentUser.getUserId(), currentUser.getLikedTorrents());
        logger.info("用户 ({}) 喜欢的种子(排除后): {}", user1Id, likedTorrentsUser1Set);
        logger.info("用户 ({}) 喜欢的种子(排除后): {}", user2Id, likedTorrentsUser2Set);
        logger.info("松果推荐的种子(排除后): {}", likedTorrentsPineconeSet);

        // 推荐种子集合
        recommendedTorrents.addAll(likedTorrentsUser1Set);
        recommendedTorrents.addAll(likedTorrentsUser2Set);
        recommendedTorrents.addAll(likedTorrentsPineconeSet);

        // 输出推荐的种子
        logger.info("推荐给用户 {} 的种子: {}", userId, recommendedTorrents);

        // 获取推荐种子的详细信息
        List<Torrent> recommendedTorrentsDetails = new ArrayList<>();
        for (String torrentId : recommendedTorrents) {
            Torrent torrent = torrentService.getById(Integer.valueOf(torrentId));  // 假设torrentService是获取种子详情的服务
            if (torrent != null) {
                recommendedTorrentsDetails.add(torrent);
            }
        }

        // 返回推荐的种子详细信息
        return JsonResult.success(recommendedTorrentsDetails);

    }

    public String torrentFormPinecone(String text) {
        try {
            // 以下是松果向量库的推荐部分
            String indexName = "ptplatform-recommendations";
            String namespace = "__default__";

            // 获取 Pinecone 索引连接
            Index index = pinecone.getIndexConnection(indexName);

            // 对查询文本进行向量化
            float[] vectorArray = pineconeService.vectorizeText(text);

            // 转换为 List<Float> 类型
            List<Float> queryVector = new ArrayList<>();
            for (float val : vectorArray) {
                queryVector.add(val);
            }

            // 创建查询向量对象
            SearchRecordsVector searchVector = new SearchRecordsVector()
                    .values(queryVector);  // 设置向量值

            // 执行查询
            SearchRecordsResponse response = index.searchRecordsByVector(
                    searchVector,
                    namespace,
                    Collections.emptyList(),  // 返回字段列表（空表示所有）
                    3,                        // topK 数量
                    null,                     // 过滤条件
                    null                      // 重排参数
            );

            // 检查响应中的 hits 数组
            if (response.getResult().getHits().isEmpty()) {
                System.out.println("No matches found!");
                return null;  // 如果没有匹配，返回 null
            } else {
                System.out.println("Matches found: " + response.getResult().getHits().size());
            }

            System.out.println("反馈如下:" + response);

            // 创建 StringBuilder 来存储结果
            StringBuilder result = new StringBuilder();

            // 遍历 hits 数组，提取每个 id 的数字部分
            for (int i = 0; i < response.getResult().getHits().size(); i++) {
                String id = response.getResult().getHits().get(i).getId();  // 获取每个 id
                String number = id.replaceAll("[^0-9]", "");  // 提取数字部分

                // 将数字部分添加到结果中，前面加逗号
                if (i > 0) {
                    result.append(",");
                }
                result.append(number);
            }

            // 返回拼接的字符串
            return result.toString();

        } catch (ApiException e) {
            // 处理 API 异常
            System.err.println("Pinecone API 异常: " + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }


    //推荐热门种子
    public JsonResult recommendHotTorrent(Integer userId){
        Set<String> recommendedTorrents = new HashSet<>();
        // 日志实例
        Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
        // 获取下载量最多的5个种子
        List<Integer> topDownloadedTorrents = getTopDownloadedTorrents();
        logger.info("热门的种子: {}", topDownloadedTorrents);

        // 将最热门的5个种子添加到推荐列表中
        recommendedTorrents.addAll(topDownloadedTorrents.stream().map(String::valueOf).collect(Collectors.toSet()));

        // 获取推荐种子的详细信息
        List<Torrent> recommendedTorrentsDetails = new ArrayList<>();
        for (String torrentId : recommendedTorrents) {
            Torrent torrent = torrentService.getById(Integer.valueOf(torrentId));  // 假设torrentService是获取种子详情的服务
            if (torrent != null) {
                recommendedTorrentsDetails.add(torrent);
            }
        }

        // 返回推荐的种子详细信息
        return JsonResult.success(recommendedTorrentsDetails);
    }


    // 获取下载量最多的三个种子
    private List<Integer> getTopDownloadedTorrents() {
        // 查询下载表，按照 torrentId 分组并统计下载次数，取前 5 个
        List<Download> topDownloads = downloadMapper.selectList(new QueryWrapper<Download>()
                .select("torrent_id, COUNT(torrent_id) as download_count")
                .groupBy("torrent_id")
                .orderByDesc("download_count")
                .last("LIMIT 5"));

        // 获取前三个种子的 torrentId
        List<Integer> topTorrentIds = topDownloads.stream()
                .map(Download::getTorrentId)
                .collect(Collectors.toList());

        return topTorrentIds;
    }



    private double calculateCosineSimilarity(String likedTags1, String likedTags2) {
        // 将标签转换为一个分数向量
        Map<String, Double> tags1 = parseTagsToMap(likedTags1);
        Map<String, Double> tags2 = parseTagsToMap(likedTags2);

        double dotProduct = 0;
        double norm1 = 0;
        double norm2 = 0;

        // 计算两个用户标签之间的点积和范数
        for (String tag : tags1.keySet()) {
            if (tags2.containsKey(tag)) {

                // 标签评分相乘，计算点积
                dotProduct += tags1.get(tag) * tags2.get(tag);
            }
            norm1 += Math.pow(tags1.get(tag), 2);  // 用户1的标签分数平方和
        }

        for (Double score : tags2.values()) {
            norm2 += Math.pow(score, 2);  // 用户2的标签分数平方和
        }

        norm1 = Math.sqrt(norm1);  // 计算用户1标签的范数
        norm2 = Math.sqrt(norm2);  // 计算用户2标签的范数

        // 计算余弦相似度
        return dotProduct / (norm1 * norm2);
    }




    private Map<String, Double> parseTagsToMap(String likedTags) {
        Map<String, Double> tagMap = new HashMap<>();
        String[] tagPairs = likedTags.split(",");
        for (String tagPair : tagPairs) {
            String[] parts = tagPair.split(":");
            if (parts.length == 2) {
                tagMap.put(parts[0].trim(), Double.parseDouble(parts[1].trim()));
            }
        }
        return tagMap;
    }

    @Transactional
    //积分兑换上传量
    public boolean exchangeUpload(Integer userId, Integer pointsToExchange) {
        // 每200积分兑换1GB上传量
        if (pointsToExchange % 200 != 0) {
            return false; // 只能按200的倍数兑换
        }

        // 1. 检查用户积分
        User user = userMapper.selectById(userId);
        if (user == null || user.getUserPoints() < pointsToExchange) {
            return false; // 积分不足
        }

        // 2. 更新用户积分
        user.setUserPoints(user.getUserPoints() - pointsToExchange);
        userMapper.updateById(user);

        // 3. 更新上传量
        user.setUploadCount(user.getUploadCount() + (float)(pointsToExchange / 200.0));
        userMapper.updateById(user);

        // 4. 记录积分兑换操作
        PointRecord pointRecord = new PointRecord();
        pointRecord.setUserId(userId);
        pointRecord.setPoints(new BigDecimal(-pointsToExchange));
        pointRecord.setPointType("exchangeUpload");
        pointRecord.setCreateTime(LocalDateTime.now());
        pointRecordMapper.insert(pointRecord);

        return true;
    }

    // 积分兑换邀请数
    @Transactional
    public boolean exchangeInvite(Integer userId, Integer pointsToExchange) {
        // 每100积分兑换1个邀请数
        if (pointsToExchange % 100 != 0) {
            return false; // 只能按100的倍数兑换
        }

        // 1. 检查用户积分
        User user = userMapper.selectById(userId);
        if (user == null || user.getUserPoints() < pointsToExchange) {
            return false; // 积分不足
        }

        // 2. 更新用户积分
        user.setUserPoints(user.getUserPoints() - pointsToExchange);
        userMapper.updateById(user);

        // 3. 更新邀请数
        user.setInviteCount(user.getInviteCount() + pointsToExchange / 100);
        userMapper.updateById(user);

        // 4. 记录积分兑换操作
        PointRecord pointRecord = new PointRecord();
        pointRecord.setUserId(userId);
        pointRecord.setPoints(new BigDecimal(-pointsToExchange));
        pointRecord.setPointType("exchangeInvite");
        pointRecord.setCreateTime(LocalDateTime.now());
        pointRecordMapper.insert(pointRecord);

        return true;
    }

    /**
     * 每小时执行一次，更新所有用户的分享率和等级
     */
//    @Scheduled(cron = "0 0 * * * ?")  // 每小时的第0分钟执行
    @Scheduled(cron = "0 0 0 * * ?") // 每天凌晨 0 点执行一次
    public void performHourlyLevelUpdate() {
        // 获取所有用户
        List<User> users = userMapper.getAllUsers();

        // 遍历所有用户，计算并更新分享率和等级
        for (User user : users) {
            updateShareRateAndLevel(user.getUserId());
        }

        System.out.println("每小时用户等级更新任务执行完毕");
    }

    /**
     * 计算分享率并更新用户等级和分享率
     */
    public void updateShareRateAndLevel(Integer userId) {
        // 获取用户的上传量和下载量
        Double uploadAmount = userMapper.getUploadAmountByUserId(userId);
        Double downloadAmount = userMapper.getDownloadAmountByUserId(userId);

        // 处理下载量为0的情况
        if (downloadAmount == 0) {
            // 如果下载量为0，无法计算分享率
            double fixedShareRate = 10.0;  // 固定分享率，设为10

            // 更新分享率为固定值
            userMapper.updateShareRate(userId, fixedShareRate);

            // 根据上传量更新用户等级，忽略分享率
            int userLevel = calculateLevelBasedOnUpload(uploadAmount);  // 仅依据上传量更新等级
            userMapper.updateUserLevel(userId, userLevel);

            // 更新权限（例如是否允许匿名评论）
            updateUserPermissions(userId, userLevel);

            return;
        }

        // 计算分享率
        double shareRate = uploadAmount / downloadAmount;

        // 更新分享率到数据库
        userMapper.updateShareRate(userId, shareRate);

        // 根据上传量和分享率更新用户等级
        int userLevel = updateUserLevel(userId, uploadAmount, shareRate);

        // 更新权限（包括是否允许匿名评论）
        updateUserPermissions(userId, userLevel);
    }

    /**
     * 更新用户权限：匿名评论
     */
    private void updateUserPermissions(Integer userId, Integer userLevel) {
        boolean allowAnonymousComment = userLevel >= 3; // 3星及以上允许匿名评论

        // 更新数据库中的权限字段
        userMapper.updateAnonymousCommentPermission(userId, allowAnonymousComment);

        // 你可以打印日志或者进行其他操作
        System.out.println("用户ID: " + userId + " - 权限更新：");
        System.out.println("允许匿名评论: " + allowAnonymousComment);
    }

    /**
     * 获取每月允许生成的邀请码数量
     */
    private int getInviteCount(int userLevel) {
        switch (userLevel) {
            case 5:
                return Integer.MAX_VALUE;  // 无限制
            case 4:
                return 10;
            case 3:
                return 5;
            case 2:
                return 3;
            case 1:
                return 1;
            default:
                return 0;  // 无权限
        }
    }

    /**
     * 根据上传量和分享率更新用户等级
     */
    private int updateUserLevel(Integer userId, Double uploadAmount, Double shareRate) {
        int level = 0;  // 默认0星

        // 根据上传量和分享率综合判断
        if (shareRate != null && shareRate >= 1.0 && uploadAmount >= 50) {
            level = 5;  // 5星用户
        } else if (shareRate != null && shareRate >= 0.5 && shareRate < 1.0 && uploadAmount >= 20) {
            level = 4;  // 4星用户
        } else if (shareRate != null && shareRate >= 0.3 && shareRate < 0.5 && uploadAmount >= 10) {
            level = 3;  // 3星用户
        } else if (shareRate != null && shareRate >= 0.2 && shareRate < 0.3 && uploadAmount >= 5) {
            level = 2;  // 2星用户
        } else if (shareRate != null && shareRate > 0 && uploadAmount >= 1) {
            level = 1;
        } else {
            level = 0;
        }
        userMapper.updateUserLevel(userId, level);
        // 返回用户等级
        return level;
    }

    // 根据上传量计算等级
    private int calculateLevelBasedOnUpload(Double uploadAmount) {
        int level = 0;  // 默认0星

        if (uploadAmount >= 50) {
            level = 5;  // 5星用户
        } else if (uploadAmount >= 20) {
            level = 4;  // 4星用户
        } else if (uploadAmount >= 10) {
            level = 3;  // 3星用户
        } else if (uploadAmount >= 5) {
            level = 2;  // 2星用户
        } else if (uploadAmount >= 1) {
            level = 1;  // 1星用户
        } else {
            level = 0;  // 0星用户
        }

        return level;
    }


    /**
     * 每月初自动重置每个用户的邀请数-根据用户等级发放数额
     */
    @Scheduled(cron = "0 0 0 1 * ?")  // 每月1号的00:00:00执行
    public void resetInviteCount() {
        // 获取所有用户
        List<User> users = userMapper.selectList(null);  // 获取所有用户

        // 遍历所有用户，重置邀请码数量
        for (User user : users) {
            int userLevel = user.getLevel();
            int inviteCount = getInviteCount(userLevel);

            // 更新每月的邀请码数量
            userMapper.updateInviteCount(user.getUserId(), inviteCount);

            // 打印日志
            System.out.println("User ID: " + user.getUserId() + " - Reset invite code count to: " + inviteCount);
        }

        System.out.println("每月邀请码数量重置任务执行完毕");
    }

    // 获取用户等级及权限返回给前端
    public JsonResult getUserLevelAndPermissions(Integer userId) {
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            return JsonResult.error("用户不存在");
        }

        // 获取用户等级（直接返回数字）
        int level = user.getLevel();

        // 获取分享率
        Double shareRate = Double.valueOf(user.getShareRate());

        // 获取用户的权限
        Map<String, Object> permissions = new HashMap<>();
        permissions.put("allowAnonymousComment", user.getAllowAnonymousComment() != null && user.getAllowAnonymousComment());  // 判断是否允许匿名评论
        permissions.put("generateInvites", user.getInviteCount());  // 直接返回数据库中的可生成邀请码数量

        // 准备返回的用户信息
        Map<String, Object> userData = new HashMap<>();
        userData.put("username", user.getUsername());
        userData.put("avatarUrl", user.getAvatarUrl());
        userData.put("nickname", user.getNickname());
        userData.put("level", level);  // 返回数字等级
        userData.put("sex", user.getSex());
        userData.put("userPoints", user.getUserPoints());
        userData.put("shareRate", shareRate);
        userData.put("inviteCount", user.getInviteCount());
        userData.put("registrationDate", user.getRegistrationDate());
        userData.put("lastLoginTime", user.getLastLoginTime());
        userData.put("introduction", user.getIntroduction());
        userData.put("role", user.getRole());
        userData.put("banStatus", user.getBanStatus());
        userData.put("banStartTime", user.getBanStartTime());
        userData.put("banEndTime", user.getBanEndTime());
        userData.put("uploadCount", user.getUploadCount());
        userData.put("downloadCount", user.getDownloadCount());

        // 返回结果
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("userData", userData);
        responseData.put("permissions", permissions);

        return JsonResult.success(responseData);
    }

    // 更新上传量和下载量
    public boolean updateUploadAndDownloadCount(Integer userId, Float uploadCount, Float downloadCount) {
        try {
            // 获取用户信息
            User user = userMapper.selectById(userId);
            if (user == null) {
                System.out.println("用户不存在");
                return false;  // 用户不存在
            }

            // 更新上传量和下载量
            user.setUploadCount(user.getUploadCount() + uploadCount);
            user.setDownloadCount(user.getDownloadCount() + downloadCount);

            // 保存更新后的用户信息
            userMapper.updateById(user);
            System.out.println("用户上传量和下载量更新成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 更新用户资料
    public boolean updateUser(User user) {
        // 只更新允许修改的字段
        int updatedRows = userMapper.updateUser(user);
        return updatedRows > 0;
    }

    public boolean checkWhetherInDate(Integer userId){
        // 首先查询用户信息
        User user = getById(userId);

        // 检查增量卡是否在有效期内
        LocalDate currentDate = LocalDate.now();
        if (user.getIncrementalCardStartTime() == null ||
                user.getIncrementalCardExpiryTime() == null ||
                currentDate.isBefore(user.getIncrementalCardStartTime()) ||
                currentDate.isAfter(user.getIncrementalCardExpiryTime())) {
            System.out.println("用户ID " + userId + " 的增量卡已过期或未生效，不执行上传量翻倍");
            return false;
        }
        return true;
    }

    // 获取积分排行榜
    public List<LeaderboardDto> getLeaderboard() {
        return userMapper.selectLeaderboard();
    }

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    //增量卡更新用户的上传量
    public void updateUserUploadCountByDouble(Integer userId, Integer torrentId) {
        // 首先查询用户信息
        User user = getById(userId);

        // 判断用户是否存在
        if (user == null) {
            System.out.println("用户ID " + userId + " 不存在，无法更新上传量");
            return;
        }

        // 检查用户是否拥有增量卡
        if (user.getHasIncrementalCard() == null || !user.getHasIncrementalCard()) {
            System.out.println("用户ID " + userId + " 没有增量卡，不执行上传量翻倍");
            return;
        }

        // 检查增量卡是否在有效期内
        LocalDate currentDate = LocalDate.now();
        if (user.getIncrementalCardStartTime() == null ||
                user.getIncrementalCardExpiryTime() == null ||
                currentDate.isBefore(user.getIncrementalCardStartTime()) ||
                currentDate.isAfter(user.getIncrementalCardExpiryTime())) {
            System.out.println("用户ID " + userId + " 的增量卡已过期或未生效，不执行上传量翻倍");
            return;
        }

        // 查询 TorrentReport 表，获取该用户与种子的上传数据
        LambdaQueryWrapper<TorrentReport> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TorrentReport::getUserId, userId)
                .eq(TorrentReport::getTorrentId, torrentId);
        System.out.println("diaoyon调用成功：");
        // 获取符合条件的所有记录
        List<TorrentReport> reports = torrentReportService.list(queryWrapper);

        // 判断是否有记录
        if (reports.isEmpty()) {
            System.out.println("没有找到与用户ID " + userId + " 和种子ID " + torrentId + " 相关的 TorrentReport 记录");
            return;
        }

        // 手动查找时间最晚的记录
        TorrentReport latestReport = reports.get(0); // 默认第一条记录是最晚的
        for (TorrentReport report : reports) {
            // 如果当前记录的 reportTime 比现有的 latestReport 更晚，更新 latestReport
            if (report.getReportTime().isAfter(latestReport.getReportTime())) {
                latestReport = report;
            }
        }


        // 将上传量（以字节为单位）转换为 GB
        Float uploadedAmount = latestReport.getUploaded() != null ? latestReport.getUploaded() / 1024.0f / 1024.0f / 1024.0f : 0; // 转换为 GB

        // 更新用户上传量
        Float currentUploadCount = user.getUploadCount() != null ? user.getUploadCount() : 0;
        user.setUploadCount(currentUploadCount + uploadedAmount);

        // 更新数据库中的用户上传量
        boolean updated = updateById(user);
        if (updated) {
            System.out.println("用户ID " + userId + " 的上传量更新成功，新的上传量为 " + user.getUploadCount() + " GB");
        } else {
            System.out.println("更新用户ID " + userId + " 的上传量失败");
        }
    }

    public boolean hasValidIncrementalCard(Integer userId) {
        // 首先查询用户信息
        User user = getById(userId);

        // 判断用户是否存在
        if (user == null) {
            System.out.println("用户ID " + userId + " 不存在，无法检查增量卡");
            return false;
        }

        // 判断用户是否拥有增量卡
        if (user.getHasIncrementalCard() == null || !user.getHasIncrementalCard()) {
            System.out.println("用户ID " + userId + " 没有增量卡");
            return false;
        }

        // 检查增量卡是否在有效期内
        LocalDate currentDate = LocalDate.now();
        if (user.getIncrementalCardStartTime() == null ||
                user.getIncrementalCardExpiryTime() == null ||
                currentDate.isBefore(user.getIncrementalCardStartTime()) ||
                currentDate.isAfter(user.getIncrementalCardExpiryTime())) {
            System.out.println("用户ID " + userId + " 的增量卡已过期或未生效");
            return false;
        }

        // 如果用户有增量卡并且在有效期内，返回 true
        return true;
    }

    //积分兑换增量卡
    @Transactional
    public boolean exchangeIncrementalCard(Integer userId, Integer pointsToExchange) {
        // 每500积分兑换1张增量卡
        if (pointsToExchange < 500 || pointsToExchange % 100 != 0) {
            System.out.println("兑换的积分不符合要求，必须为500的倍数。");
            return false; // 只能按500的倍数兑换
        }

        User user = userMapper.selectById(userId);
        if (user == null || user.getUserPoints() < pointsToExchange) {
            System.out.println("用户积分不足，无法兑换增量卡");
            return false; // 积分不足
        }

        // 检查用户是否已经有增量卡
        if (user.getHasIncrementalCard() != null && user.getHasIncrementalCard()) {
            System.out.println("用户ID " + userId + " 已经拥有增量卡，无法再次兑换");
            return false; // 用户已经拥有增量卡
        }

        // 更新用户积分
        user.setUserPoints(user.getUserPoints() - pointsToExchange);
        userMapper.updateById(user);

        // 设置增量卡的开始和过期时间
        LocalDate currentDate = LocalDate.now();
        user.setHasIncrementalCard(true);
        user.setIncrementalCardStartTime(currentDate);
        user.setIncrementalCardExpiryTime(currentDate.plusDays(7)); // 增量卡有效期7天

        // 更新用户信息，保存增量卡状态
        userMapper.updateById(user);

        // 记录积分兑换操作
        PointRecord pointRecord = new PointRecord();
        pointRecord.setUserId(userId);
        pointRecord.setPoints(new BigDecimal(-pointsToExchange)); // 负值表示消费
        pointRecord.setPointType("exchangeIncrementalCard");
        pointRecord.setCreateTime(LocalDateTime.now());
        pointRecordMapper.insert(pointRecord);

        System.out.println("用户ID " + userId + " 成功兑换了增量卡，新的积分余额为 " + user.getUserPoints());
        System.out.println("增量卡开始时间为：" + user.getIncrementalCardStartTime());
        System.out.println("增量卡有效期至：" + user.getIncrementalCardExpiryTime());

        return true;
    }

    // 定时任务，每天凌晨 1 点执行
    @Scheduled(cron = "0 0 1 * * ?")
    @Transactional
    public void checkAndUpdateIncrementalCardStatus() {
        // 获取所有有增量卡的用户
        List<User> usersWithIncrementalCard = userMapper.selectUsersWithIncrementalCard();

        // 获取当前日期
        LocalDate currentDate = LocalDate.now();

        // 检查用户的增量卡是否过期
        for (User user : usersWithIncrementalCard) {
            if (user.getIncrementalCardExpiryTime().isBefore(currentDate)) {
                // 如果增量卡已过期，更新 hasIncrementalCard 为 false
                user.setHasIncrementalCard(false);
                userMapper.updateById(user);
                System.out.println("用户ID " + user.getUserId() + " 的增量卡已过期，已更新状态为无增量卡");
            }
        }
    }

    //获取用户增量卡状态
    public User getUserDoubleStatusById(Integer userId) {
        return userMapper.selectById(userId);
    }

}


// 用户相似度的辅助类
class UserSimilarity {
    private Integer userId;
    private double similarity;

    public UserSimilarity(Integer userId, double similarity) {
        this.userId = userId;
        this.similarity = similarity;
    }

    public Integer getUserId() {
        return userId;
    }

    public double getSimilarity() {
        return similarity;
    }
}
